package intelligentrecommender.phases.phrasesextractor;

import edu.stanford.nlp.ie.AbstractSequenceClassifier;
import edu.stanford.nlp.ie.crf.CRFClassifier;
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import intelligentrecommender.phases.utilities.TagInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Eias Tawil
 */
public class PhrasesExtractor {

    //private String EXAMPLE_TEST = "eias do good job and good job is good job Abed iug. iug is a iug bad university. iug bad university is iug. bad students are nauty. students go to a bad university. I teach software engineering. civil engineering and michanical engineering departments in iug bad university";
    private HashMap<String, Integer> map1 = new HashMap<>();
    private HashMap<String, Integer> map2 = new HashMap<>();
    private HashMap<String, Integer> map3 = new HashMap<>();
    private HashMap<String, Integer> locations = new HashMap<>();
    private HashMap<String, Integer> persons = new HashMap<>();
    private final int threshold = 5;
    private String mapkey;
    private String dataString = "";
    TagInfo ti;

    public PhrasesExtractor(String data) {
        //process(data);
        //Pattern pat = Pattern.compile("(\\w)(\\s+)([\\.,])");
        //Pattern pat = Pattern.compile("[^\\p{L}\\p{N}]");
        //dataString.replaceAll("http.*?\\s", " ");
        data = data.replaceAll("\\W+", " ");
        //Pattern pat = Pattern.compile("[ \t\n,\\.\"!?$~()\\[\\]\\{\\}:;/\\\\<>+=%*]");
        //Matcher mat = pat.matcher(dataString);
        //dataString = mat.replaceAll(" "); // Replace all non-word characters with whitespace

        //dataString = data;

        extractImportantPhrases(data);

        //dataString = dataString.replaceAll("\\s+", " ");

        firstLevel();
        secondLevel();
        thirdLevel();
        checkForRedundancyForMap1();
        checkForRedundancyForMap2();

        System.out.println("First Level");
        System.out.println(map1);
        System.out.println("\nSecond Level");
        System.out.println(map2);
        System.out.println("\nThird Level");
        System.out.println(map3);
        System.out.println("\nLocations");
        System.out.println(locations);
        System.out.println("\nPersons");
        System.out.println(persons);
    }

    // First Map -- Phrase of one word
    private void firstLevel() {
        String[] splits = dataString.split("\\s+"); // Splitting the text on whitespace characters
        //Loop over the words and add each other to the map
        for (String word : splits) {
            Pattern pattern = Pattern.compile(word);
            Matcher matcher = pattern.matcher(dataString);
            //Check if the text contain the phrase to be added
            int numberOfMatches = 0;
            while (matcher.find()) {
                numberOfMatches++;
            }
            if (numberOfMatches >= threshold) {
                map1.put(word, numberOfMatches);//Insert the new entry
            }
        }
    }

    // Second Map -- Phrase of two words
    private void secondLevel() {
        for (Map.Entry<String, Integer> ex : map1.entrySet()) {
            for (Map.Entry<String, Integer> in : map1.entrySet()) {
                //if (!(ex.getKey().equals(in.getKey()))) {
                mapkey = ex.getKey() + " " + in.getKey();
                Pattern pattern = Pattern.compile(mapkey);
                Matcher matcher = pattern.matcher(dataString);
                //Check if the text contain the phrase to be added
                int numberOfMatches = 0;
                while (matcher.find()) {
                    numberOfMatches++;
                }
                if (numberOfMatches >= threshold) {
                    map2.put(mapkey, numberOfMatches);//Insert the new entry
                }
                //}
            }
        }
        //stage++;
    }

    // Third Map -- Phrase of three words
    private void thirdLevel() {
        for (Map.Entry<String, Integer> m1 : map1.entrySet()) {
            for (Map.Entry<String, Integer> m2 : map2.entrySet()) {
                mapkey = m2.getKey() + " " + m1.getKey();
                Pattern pattern = Pattern.compile(mapkey);
                Matcher matcher = pattern.matcher(dataString);
                //Check if the text contain the phrase to be added
                int numberOfMatches = 0;
                while (matcher.find()) {
                    numberOfMatches++;
                }
                if (numberOfMatches >= threshold) {
                    map3.put(mapkey, numberOfMatches);//Insert the new entry
                }
            }
        }
    }

    // Third Map -- Phrase of three words
    private void thirdLevel2() {
        for (Map.Entry<String, Integer> m1 : map1.entrySet()) {
            for (Map.Entry<String, Integer> m2 : map1.entrySet()) {
                for (Map.Entry<String, Integer> m3 : map1.entrySet()) {
                    mapkey = m3.getKey() + " " + m2.getKey() + " " + m1.getKey();
                    Pattern pattern = Pattern.compile(mapkey);
                    Matcher matcher = pattern.matcher(dataString);
                    //Check if the text contain the phrase to be added
                    int numberOfMatches = 0;
                    while (matcher.find()) {
                        numberOfMatches++;
                    }
                    if (numberOfMatches >= threshold) {
                        map3.put(mapkey, numberOfMatches);//Insert the new entry
                    }
                }
            }
        }
    }

    private void checkForRedundancyForMap1() {
        List<String> map1Keys = new ArrayList<>();
        for (Map.Entry<String, Integer> m1 : map1.entrySet()) {
            map1Keys.add(m1.getKey());
        }

        for (Map.Entry<String, Integer> m2 : map2.entrySet()) {
            //for (Map.Entry<String, Integer> m1 : map1.entrySet()) {
            for (String m1 : map1Keys) {
                Pattern pattern = Pattern.compile(m1);
                Matcher matcher = pattern.matcher(m2.getKey());
                while (matcher.find()) {
                    map1.remove(m1);
                }
                //}
            }
        }
    }

    private void checkForRedundancyForMap2() {
        List<String> map2Keys = new ArrayList<>();
        for (Map.Entry<String, Integer> m2 : map2.entrySet()) {
            map2Keys.add(m2.getKey());
        }
        for (Map.Entry<String, Integer> m3 : map3.entrySet()) {
            for (String m2 : map2Keys) {
                Pattern pattern = Pattern.compile(m2);
                Matcher matcher = pattern.matcher(m3.getKey());
                while (matcher.find()) {
                    map2.remove(m2);
                }
            }
        }
    }

    private void extractImportantPhrases(String text) {
        String serializedClassifier = "src/intelligentrecommender/phases/utilities/classifiers/english.all.3class.distsim.crf.ser.gz";
        AbstractSequenceClassifier<CoreLabel> classifier = CRFClassifier.getClassifierNoExceptions(serializedClassifier);
        for (List<CoreLabel> lcl : classifier.classify(text)) {
            for (CoreLabel cl : lcl) {
                switch (cl.getString(CoreAnnotations.AnswerAnnotation.class)) {
                    case "LOCATION":
                        locations.put(cl.getString(CoreAnnotations.TextAnnotation.class), 0);
                        break;
                    case "PERSON":
                        persons.put(cl.getString(CoreAnnotations.TextAnnotation.class), 0);
                        break;
                    default:
                        dataString += cl.getString(CoreAnnotations.TextAnnotation.class) + " ";
                        break;
                }
            }
        }
    }

    /*public static void main(String args[]) {
     new PhrasesExtractor("eias do good job and good job is good job Abed iug. eias do good iug is a iug bad university. iug bad university is iug. eias do good bad students are nauty. students go to a bad university. I teach software engineering. civil engineering and michanical engineering departments in iug bad university");
     }*/
}